//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommunityServer.Components;

namespace CommunityServer.Controls {

	// *********************************************************************
	//  Login
	//
	/// <summary>
	/// This server control renders and handles the login UI for the user.
	/// </summary>
	// ***********************************************************************/
	[
		ParseChildren(true)
	]
	public class Login : SecureTemplatedWebControl {

		CSContext csContext = CSContext.Current;
		TextBox username;
		TextBox password;
		IButton loginButton;
		CheckBox autoLogin;

		UserInvitation invitation = null;

		// *********************************************************************
		//  Login
		//
		/// <summary>
		/// Constructor
		/// </summary>
		// ***********************************************************************/
		public Login() : base() {

			if (csContext.SiteSettings.AccountActivation == AccountActivation.InvitationOnly && !Globals.IsNullorEmpty(csContext.Context.Request["InvitationKey"]))
			{
				Guid invitationKey = Guid.Empty;
				try
				{
					invitationKey = new Guid(csContext.Context.Request["InvitationKey"]);
				}
				catch
				{
				}

				if (invitationKey != Guid.Empty)
					invitation = UserInvitations.GetUserInvitation(invitationKey);
			}
	
		}

		protected string ReferralLink
		{
			get
			{
				return ViewState["ReferralLink"] as string;
			}
			set
			{
				ViewState["ReferralLink"] = value;
			}
		}

		protected override void OnInit(EventArgs e)
		{
			this.EnableViewState = true;
			base.OnInit (e);
		}


		protected override void OnLoad(EventArgs e)
		{


			base.OnLoad (e);

			if(!Page.IsPostBack)
			{
				Uri referral =  Context.Request.UrlReferrer;
				if(referral != null)
					ReferralLink = referral.ToString();
			}


		}


		// *********************************************************************
		//  CreateChildControls
		//
		/// <summary>
		/// This event handler adds the children controls.
		/// </summary>
		// ***********************************************************************/
		protected override void CreateChildControls() 
		{
			// If the user is already authenticated we have no work to do
			if(Page.Request.IsAuthenticated)
			{
				// If the URL is for the login page and the user is already logged in
				// we need to throw an access denied exception
				if (Globals.GetSiteUrls().Login.StartsWith(csContext.Context.Request.Path)) 
					throw new CSException (CSExceptionType.UserAlreadyLoggedIn, csContext.ReturnUrl);

				return;
			}

			base.CreateChildControls();
		}

		protected override void AttachChildControls()
		{
			// Find the username control
			username = (TextBox) FindControl("username");

			// Find the password control
			password = (TextBox) FindControl("password");

			// Find the login button
			loginButton = ButtonManager.Create(FindControl("loginButton"));

			loginButton.Click += new EventHandler(LoginButton_Click);
			loginButton.Text = ResourceManager.GetString("LoginSmall_Button");

			// Find the autologin checkbox
			autoLogin = (CheckBox) FindControl("autoLogin");
			autoLogin.Text = ResourceManager.GetString("LoginSmall_AutoLogin");		
            //autoLogin.AutoPostBack = true;
            //autoLogin.CheckedChanged += new EventHandler( AutoLogin_OnCheckedChanged );
            
            // Restore autologin status from the auto login cookie
            AutoLoginCookie alCookie = new AutoLoginCookie();
            autoLogin.Checked = alCookie.GetValue();

			RegisterSetFocusScript();
		}

        /// <summary>
        /// Event handler to update auto login cookie value.
        /// </summary>
        protected void AutoLogin_OnCheckedChanged (Object sender, EventArgs e) {
            AutoLoginCookie alCookie = new AutoLoginCookie();
            alCookie.Write( autoLogin.Checked );
        }

		// *********************************************************************
		//  LoginButton_Click
		//
		/// <summary>
		/// Event handler to handle the login button click event
		/// </summary>
		// ***********************************************************************/
		public void LoginButton_Click (Object sender, EventArgs e) {
			
			User userToLogin = new User();
			

            // Save in cookie auto login user's preference
            // only if it wasn't previously set or the cookie value differs from
            // login's autologin checkbox status.
            //
            AutoLoginCookie alCookie = new AutoLoginCookie();
            if (!alCookie.HasValue ||
                (alCookie.HasValue && (alCookie.GetValue() != autoLogin.Checked))) 
            {
                alCookie.Write( autoLogin.Checked );
            } 

			if (!Page.IsValid)
				return;

			userToLogin.Username = username.Text;
			userToLogin.Password = password.Text;
            
			LoginUserStatus loginStatus = Users.ValidUser(userToLogin);
            ProcessLoginRequest(userToLogin, loginStatus, autoLogin.Checked);

        }

        protected void ProcessLoginRequest(User userToLogin, LoginUserStatus loginStatus, bool autoLoginUser)
        {
            bool enableBannedUsersToLogin = csContext.SiteSettings.EnableBannedUsersToLogin;
            string redirectUrl = null;

            // Change to let banned users in
            //
            if (loginStatus == LoginUserStatus.Success || (enableBannedUsersToLogin && loginStatus == LoginUserStatus.AccountBanned))
            {
                // Are we allowing login?
                // TODO -- this could be better optimized
                if (!csContext.SiteSettings.AllowLogin && !userToLogin.IsAdministrator)
                {
                    throw new CSException(CSExceptionType.UserLoginDisabled);
                }

                HttpCookie formsAuthCookie;
                formsAuthCookie = FormsAuthentication.GetAuthCookie(userToLogin.Username, autoLoginUser);
                
                formsAuthCookie = AlterAuthCookie(formsAuthCookie);
                
                UserCookie userCookie = csContext.User.GetUserCookie();
                userCookie.WriteCookie(formsAuthCookie, 30, autoLoginUser);

                // if we're logging in with an invitation, accept the invitation
                if (invitation != null)
                    UserInvitations.Accept(invitation, csContext.User);

                // Get the link from the context
                if (!Globals.IsNullorEmpty(csContext.ReturnUrl))
                    redirectUrl = csContext.ReturnUrl;

                // If none, get the stored redirect url
                if ((redirectUrl == null) && (ReferralLink != null) && (ReferralLink.Trim() != string.Empty))
                    redirectUrl = ReferralLink;

                // Check to ensure we aren't redirecting back to a Message prompt or back to the logout screen
                // Or ChangePassword*, or CreateUser*, or EmailForgottenPassword*
                // Or, if no URL, use appPath
                if (Globals.IsNullorEmpty(redirectUrl)
                    || (redirectUrl.IndexOf("MessageID") != -1)
                    || (redirectUrl.IndexOf(Globals.GetSiteUrls().Logout) != -1)
                    || (redirectUrl.IndexOf("ChangePassword") != -1)
                    || (redirectUrl.IndexOf("EmailForgottenPassword") != -1))
                    redirectUrl = Globals.GetSiteUrls().Home;

                if (invitation != null)
                    redirectUrl = Globals.GetSiteUrls().Message(CSExceptionType.UserInvitationAccepted);

                LeaveSecureConnection(redirectUrl);
            }
            else if (loginStatus == LoginUserStatus.InvalidCredentials)
            {
                // Invalid Credentials
                LeaveSecureConnection(Globals.GetSiteUrls().Message(CSExceptionType.UserInvalidCredentials));
            }
            else if (loginStatus == LoginUserStatus.AccountPending)
            {
                // Account not approved yet
                LeaveSecureConnection(Globals.GetSiteUrls().Message(CSExceptionType.UserAccountPending));
            }
            else if (loginStatus == LoginUserStatus.AccountDisapproved)
            {
                // Account disapproved
                LeaveSecureConnection(Globals.GetSiteUrls().Message(CSExceptionType.UserAccountDisapproved));
            }
            else if (loginStatus == LoginUserStatus.UnknownError)
            {
                // Unknown error because of miss-syncronization of internal data
                throw new CSException(CSExceptionType.UserUnknownLoginError);
            }
            // Reject banned users if they are not allowed to
            // pass through login.
            //
            else if (!enableBannedUsersToLogin && loginStatus == LoginUserStatus.AccountBanned)
            {
                // Account banned
                LeaveSecureConnection(Globals.GetSiteUrls().Message(CSExceptionType.UserAccountBanned));
            }
        }

	    /// <summary>
	    /// This method can be overridden to alter settings in the auth cookie such as the Domain
	    /// </summary>
	    /// <param name="cookie"></param>
	    /// <returns></returns>
        protected virtual HttpCookie AlterAuthCookie(HttpCookie cookie)
	    {
	        return cookie;
	    }

	    private void RegisterSetFocusScript()
		{
			string key = "LoginOnFocus";
			if(Page.IsStartupScriptRegistered(key))
				return;

			string script = @"
					<script language=""javascript"">
					<!--
						document.forms[0].{0}.focus()
					-->
					</script>";
	  
			Page.RegisterStartupScript("LoginOnFocus", string.Format(script, username.ClientID) ) ;
			
		}
	}
}
